一、什麼是可變與不可變?
(一)原始值是不可變的(immutable)
原始值(Primitives)和物件型別(Object)有一個基本差異存在,原始值是不可變的(immutable),沒辦法改變原始值,或是改變數字是沒有意義的。但原始值中的「字串」,不可變的特性沒那麼明顯,因為字串就像是字元的陣列(arrays of characters),但仍然是不可變的。
字串是不可改變的:
let s = "hello!";
s.toUpperCase(); //回傳"HELLO"
s; //回傳 "hello" 原本的字串
(二)原始值為by value 做比較:
原始值 (Primitives)比較時,是藉由值(by value) 比較的,意思是兩個擁有「相同的值」才會視為相同。為什麼說字串不明顯呢? 兩個字串如果拿來被比較,在長度相同、每個索引值都一樣的情況下,才會視為相等。
原始值兩個擁有相同的值,為相等:
let a = 10;
let b = 10;
a === b; //true 兩個變數,值相等即為相等
(三)物件是可變的(mutable),也就是物件的值可以改變:
let o = {x:1};
o.x = 2; //更改物件內的x
o.y = 3; //新增物件內容y
o; //{x: 2, y: 3}
(四)物件是by reference 做比較:
物件有時被稱為(Reference types),這和原始型別不同。物件值就是參考 (references),也就是以參考(by reference)作為比較。兩個物件只有在參考(refer)相同比層的物件時,才會被視為相等。
兩個物件就算內容一樣也不相等:
let c = {value:10};
let d = {vlaue:10};
c === d; //false
如何才能讓物件相等呢?
let a = [];
let b = a;
a === b; //true a與b都參考相同的物件,所以他們兩個相等
(五)變數更新與傳遞
let a = 10;
let b = a;
a; //10
b; //10
a=100;
a; //100
b; //10
let c = {value:50};
let b = c;
b; //{value:50}
c; //{value:50}
c.value = 100; 更改c的value值
c; //{value:100}
b; //{value:100} 也跟著變成100了
(六)什麼是pass by sharing?
當function參數中的物件被重新賦予值的時候,function外面的變數內容是不會被影響的。
const a = {value:200};
function changeValue(object1){
object1 = {value:123}; //賦予值
}
changeValue(a);
console.log(a); //{value:200} 仍然是{value:200} 沒有變成function內賦予的值
如果不是賦予值,就會像之前的by reference狀況一樣
const c = {value:300};
function changeValue(object2){
object2.value = 500; //更新value值,並非重新賦予值
}
changeValue(c);
console.log(c); //{value:500}
(七)既然物件型別是傳址(by reference),那如何創建一個一模一樣的新物件(陣列)?
必須使用迴圈loop,用來明確拷貝該物件或陣列內的每一個元素:
let a = ["a","b","c"]; //想要拷貝的陣列
let b = []; //想要將a陣列內容拷貝到b
for(let i=0; i<a.length; i++){ //a[]內的每個索引,都要拷貝到b內部
b[i] = a[i];
}
let c = Array.from(b); //ES6中,用Array.from拷貝一個陣列
console.log(c); // ['a', 'b', 'c']
(八)如何比較兩個不同的物件或陣列?
let a = ["a","b","c"]; //想要拷貝的陣列
let b = [];
function equalArrays(a,b){
if(a===b) return true; //同一個陣列是相等的
if(a.length !== b.length) return false; //大小不同的陣列是不相等的
for(let i=0; i<a.length; i++){
if(a[i] !== b[i]) return false; //兩個陣列內的內容不相等,陣列不相等
}
return true; //否則他們就是相等的
}
補充:
JavaScript 中的資料型別,分為基本型別(Primitives)和物件型別(Object)。
基本型別包含:
不是上述的都算物件型別:
Reference
重新認識 JavaScript 008天
https://developer.mozilla.org/en-US/docs/Glossary/Immutable